package com.jg.visitor.common.utils;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jg.visitor.common.bean.ServiceCode;
import com.jg.visitor.config.exception.JgException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


@Slf4j
@Component
public class JsonService {
    private static final ObjectMapper mapper = new ObjectMapper();

    public <T> T jsonToObject(String jsonString, Class<?> collectionClass, Class<?>... elementClasses) throws JgException {
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
            return mapper.readValue(jsonString, javaType);
        } catch (Exception e) {
            log.error("jsonToObject", e);
            throw new JgException(ServiceCode.JSON_TO_OBJECT_ERROR);
        }
    }

    public <T> T jsonToObject(String jsonString, Class<T> clazz) throws JgException {
        try {
            return mapper.readValue(CheckParamUtil.verify(jsonString), clazz);
        } catch (Exception e) {
            log.error("jsonToObject", e);
            throw new JgException(ServiceCode.JSON_TO_OBJECT_ERROR);
        }
    }

    public String objectToJson(Object object) throws JgException {
        try {
            return mapper.writeValueAsString(object);
        } catch (Exception e) {
            log.error("objectToJson", e);
            throw new JgException(ServiceCode.OBJECT_TO_JSON_ERROR);
        }
    }

    static {
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
    }

    @Slf4j
    public static class CheckParamUtil {

        public CheckParamUtil() {
        }

        public static String verify(String input) {
            if (null == input) {
                return "";
            } else {
                char[] originalChars = input.toCharArray();
                char[] chars = new char[originalChars.length];

                System.arraycopy(originalChars, 0, chars, 0, originalChars.length);

                return new String(chars);
            }
        }
    }
}
